/*
 *
 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/**********************************************************************
 **********************************************************************
 **********************************************************************
 *** COPYRIGHT (c) 1997-1998 Eastman Kodak Company.                 ***
 *** As  an unpublished  work pursuant to Title 17 of the United    ***
 *** States Code.  All rights reserved.                             ***
 **********************************************************************
 **********************************************************************
 **********************************************************************/

package com.sun.image.codec.jpeg;


/**
 * Class to encapsulate the JPEG quantization tables.
 * <p>
 * Note that the classes in the com.sun.image.codec.jpeg package are not
 * part of the core Java APIs.  They are a part of Sun's JDK and JRE
 * distributions.  Although other licensees may choose to distribute these
 * classes, developers cannot depend on their availability in non-Sun
 * implementations.  We expect that equivalent functionality will eventually
 * be available in a core API or standard extension.
 * <p>
 */
public class JPEGQTable {

  /**
   * Quantization step for each coefficient in zig-zag order
   */
  private int quantval[];

  /**
   * The number of coefficients in a DCT block
   */
  private static final byte QTABLESIZE = 64;

  /**
   * This is the sample luminance quantization table given in the
   * JPEG spec section K.1, expressed in zigzag order. The spec says
   * that the values given produce "good" quality, and when divided
   * by 2, "very good" quality.
   */
  public static final JPEGQTable StdLuminance = new JPEGQTable();

  static {
    int[] lumVals = {
        16, 11, 12, 14, 12, 10, 16, 14,
        13, 14, 18, 17, 16, 19, 24, 40,
        26, 24, 22, 22, 24, 49, 35, 37,
        29, 40, 58, 51, 61, 60, 57, 51,
        56, 55, 64, 72, 92, 78, 64, 68,
        87, 69, 55, 56, 80, 109, 81, 87,
        95, 98, 103, 104, 103, 62, 77, 113,
        121, 112, 100, 120, 92, 101, 103, 99
    };

    StdLuminance.quantval = lumVals;
  }

  /**
   * This is the sample luminance quantization table given in the
   * JPEG spec section K.1, expressed in zigzag order. The spec says
   * that the values given produce "good" quality, and when divided
   * by 2, "very good" quality.
   */
  public static final JPEGQTable StdChrominance = new JPEGQTable();

  static {
    int[] chromVals = {
        17, 18, 18, 24, 21, 24, 47, 26,
        26, 47, 99, 66, 56, 66, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99,
        99, 99, 99, 99, 99, 99, 99, 99
    };
    StdChrominance.quantval = chromVals;
  }


  /**
   * Constructs an empty quantization table. This is used to create
   * the Std Q-Tables.
   */
  private JPEGQTable() {
    quantval = new int[QTABLESIZE];
  }

  /**
   * Constructs an quantization table from the array that was
   * passed.  The coefficents must be in zig-zag order. The array
   * must be of length 64.
   *
   * @param table the quantization table (this is copied).
   */
  public JPEGQTable(int table[]) {
    if (table.length != QTABLESIZE) {
      throw new IllegalArgumentException
          ("Quantization table is the wrong size.");
    } else {
      quantval = new int[QTABLESIZE];
      System.arraycopy(table, 0, quantval, 0, QTABLESIZE);
    }
  }


  /**
   * Returns the current quantization table as an array of ints in
   * zig zag order.
   *
   * @return A copy of the contained quantization table.
   */
  public int[] getTable() {
    int[] table = new int[QTABLESIZE];
    System.arraycopy(quantval, 0, table, 0, QTABLESIZE);
    return table;
  }

  /**
   * Returns a new Quantization table where the values are
   * multiplied by scaleFactor and then clamped to the range
   * 1..32767 (or to 1..255 if forceBaseline is 'true'). <P>
   *
   * Values less than one tend to improve the quality level of the
   * table, and values greater than one degrade the quality level of
   * the table.
   *
   * @param scaleFactor the multiplication factor for the table
   * @param forceBaseline if true the values will be clamped to the range  [1 .. 255]
   * @return A new Q-Table that is a linear multiple of this Q-Table
   */
  public JPEGQTable getScaledInstance(float scaleFactor,
      boolean forceBaseline) {
    long max = (forceBaseline) ? 255L : 32767L;
    int[] ret = new int[QTABLESIZE];

    for (int i = 0; i < QTABLESIZE; i++) {
      long holder = (long) ((quantval[i] * scaleFactor) + 0.5);

      // limit to valid range
      if (holder <= 0L) {
        holder = 1L;
      }

      // Max quantizer for 12 bits
      if (holder > max) {
        holder = max;
      }

      ret[i] = (int) holder;
    }
    return new JPEGQTable(ret);
  }
}
